#include <asm/asm.h>
#include <macros.h>

restore_all:
	popq	%rax
	movq	%rax,	%es

	popq	%rax
	movq	%rax,	%ds

	popq	%r15
	popq	%r14
	popq	%r13
	popq	%r12
	popq	%r11
	popq	%r10
	popq	%r9
	popq	%r8
	popq	%rbp
	popq	%rdi
	popq	%rsi
	popq	%rdx
	popq	%rcx
	popq	%rbx
	popq	%rax
	addq    $0x10, %rsp #跳过错误码和函数指针
	iretq

isr_call_comm:
# 以下所有中断异常步骤都是一致的
	cld
	pushq   %rax
	pushq	%rbx
	pushq	%rcx
	pushq	%rdx
	pushq	%rsi
	pushq	%rdi
	pushq	%rbp
	pushq	%r8
	pushq	%r9
	pushq	%r10
	pushq	%r11
	pushq	%r12
	pushq	%r13
	pushq	%r14
	pushq	%r15
	xorq    %rax, %rax
	movq	%ds,	%rax
	pushq	%rax
	xorq    %rax, %rax
	movq	%es,	%rax
	pushq	%rax
	movq $SYS_DATA64_IDX, %rdi
	movq %rdi, %es
	movq %rdi, %ds

# x86-64 参数传递从左到右依次 rdi rsi rdx rcx r8 r9
	movq %rsp, %rdi #将intr_arg_t指针作为函数参数
	movq GET_FUNC_POINT(%rsp), %rax #获取函数指针
    callq *%rax

	jmp restore_all


BEGIN_FUNC(restore_from_intr)
	jmp restore_all
END_FUNC(restore_from_intr)

BEGIN_FUNC(divide_error_isr)
	pushq $0 # 错误码
	pushq %rax
	leaq do_divide_error_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(divide_error_isr)


BEGIN_FUNC(debug_isr)
	pushq $0 # 错误码
	pushq %rax
	leaq do_debug_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(debug_isr)

BEGIN_FUNC(nmi_isr)
    pushq $0 #错误码的位置
	cld
	pushq $0 #函数指针的位置
	pushq   %rax
	pushq	%rbx
	pushq	%rcx
	pushq	%rdx
	pushq	%rsi
	pushq	%rdi
	pushq	%rbp
	pushq	%r8
	pushq	%r9
	pushq	%r10
	pushq	%r11
	pushq	%r12
	pushq	%r13
	pushq	%r14
	pushq	%r15
	xorq    %rax,   %rax
	movq	%ds,	%rax
	pushq	%rax
	xorq    %rax,   %rax
	movq	%es,	%rax
	pushq	%rax

	movq	$SYS_DATA64_IDX,	%rax
	movq	%rax,	%ds
	movq	%rax,	%es

	movq %rsp, %rdi #将intr_arg_t指针作为函数参数
    callq do_nmi_isr


    jmp restore_all

END_FUNC(nmi_isr)


BEGIN_FUNC(int3_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_int3_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm

END_FUNC(int3_isr)



BEGIN_FUNC(into_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_into_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(into_isr)



BEGIN_FUNC(bound_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_bound_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(bound_isr)



BEGIN_FUNC(ud2_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_ud2_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(ud2_isr)


BEGIN_FUNC(fwait_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_fwait_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(fwait_isr)


BEGIN_FUNC(double_fault_isr)
#ifdef BOCHS_DEBUG_POINT
	xchgw %bx, %bx
#endif
	pushq %rax
	leaq do_double_fault_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(double_fault_isr)

BEGIN_FUNC(coprocessor_segment_cross_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_coprocessor_segment_cross_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(coprocessor_segment_cross_isr)


BEGIN_FUNC(invalid_tss_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_invalid_tss_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(invalid_tss_isr)


BEGIN_FUNC(segment_not_exist_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_segment_not_exist_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(segment_not_exist_isr)


BEGIN_FUNC(stack_segment_fault_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_stack_segment_fault_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(stack_segment_fault_isr)

BEGIN_FUNC(general_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_general_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(general_isr)


BEGIN_FUNC(page_fault_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_page_fault_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(page_fault_isr)


BEGIN_FUNC(fpe_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_fpe_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(fpe_isr)


BEGIN_FUNC(align_check_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_align_check_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(align_check_isr)


BEGIN_FUNC(machine_check_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_machine_check_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(machine_check_isr)



BEGIN_FUNC(simd_fpe_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_simd_fpe_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(simd_fpe_isr)



BEGIN_FUNC(virtual_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_virtual_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(virtual_isr)


BEGIN_FUNC(control_protection_exception_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_control_protection_exception_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(control_protection_exception_isr)



BEGIN_FUNC(hypervisor_injection_excetion_isr)
    pushq $0 # 错误码
	pushq %rax
	leaq do_hypervisor_injection_excetion_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(hypervisor_injection_excetion_isr)




BEGIN_FUNC(vmm_communication_exception_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_vmm_communication_exception_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(vmm_communication_exception_isr)



BEGIN_FUNC(security_exception_isr)
    # 错误码 由处理器自动添加
	pushq %rax
	leaq do_security_exception_isr(%rip), %rax
	xchgq %rax, (%rsp) #函数指针存放在此

	jmp isr_call_comm
END_FUNC(security_exception_isr)

BEGIN_FUNC(unkonw_intr_isr)
    pushq $0 #错误码的位置
	cld
	pushq $0 #函数指针的位置
	pushq   %rax
	pushq	%rbx
	pushq	%rcx
	pushq	%rdx
	pushq	%rsi
	pushq	%rdi
	pushq	%rbp
	pushq	%r8
	pushq	%r9
	pushq	%r10
	pushq	%r11
	pushq	%r12
	pushq	%r13
	pushq	%r14
	pushq	%r15
	xorq    %rax,   %rax
	movq	%ds,	%rax
	pushq	%rax
	xorq    %rax,   %rax
	movq	%es,	%rax
	pushq	%rax


	movq	$SYS_DATA64_IDX,	%rax
	movq	%rax,	%ds
	movq	%rax,	%es

	movq %rsp, %rdi #将intr_arg_t指针作为函数参数
    callq do_unkonw_intr_isr


    jmp restore_all
END_FUNC(unkonw_intr_isr)